static gboolean opt_require_hardlinks;
static gboolean opt_force_copy;
static gboolean opt_bareuseronly_dirs;
+static char *opt_selinux_policy;
+static char *opt_selinux_prefix;
static gboolean
parse_fsync_cb (const char *option_name,
if (!ot_parse_boolean (value, &val, error))
return FALSE;
-
+
opt_disable_fsync = !val;
return TRUE;
{ "require-hardlinks", 'H', 0, G_OPTION_ARG_NONE, &opt_require_hardlinks, "Do not fall back to full copies if hardlinking fails", NULL },
{ "force-copy", 'C', 0, G_OPTION_ARG_NONE, &opt_force_copy, "Never hardlink (but may reflink if available)", NULL },
{ "bareuseronly-dirs", 'M', 0, G_OPTION_ARG_NONE, &opt_bareuseronly_dirs, "Suppress mode bits outside of 0775 for directories (suid, world writable, etc.)", NULL },
+ { "selinux-policy", 0, 0, G_OPTION_ARG_FILENAME, &opt_selinux_policy, "Set SELinux labels based on policy in root filesystem PATH (may be /); implies --force-copy", "PATH" },
+ { "selinux-prefix", 0, 0, G_OPTION_ARG_STRING, &opt_selinux_prefix, "When setting SELinux labels, prefix all paths by PREFIX", "PREFIX" },
{ NULL }
};
* convenient infrastructure for testing C APIs with data.
*/
if (opt_disable_cache || opt_whiteouts || opt_require_hardlinks ||
- opt_union_add || opt_force_copy || opt_bareuseronly_dirs || opt_union_identical)
+ opt_union_add || opt_force_copy || opt_bareuseronly_dirs || opt_union_identical ||
+ opt_selinux_policy || opt_selinux_prefix)
{
OstreeRepoCheckoutAtOptions options = { 0, };
+ /* do this early so option checking also catches force copy conflicts */
+ if (opt_selinux_policy)
+ opt_force_copy = TRUE;
+
if (opt_user_mode)
options.mode = OSTREE_REPO_CHECKOUT_MODE_USER;
/* Can't union these */
glnx_throw (error, "Cannot specify both --require-hardlinks and --force-copy");
goto out;
}
+ if (opt_selinux_prefix && !opt_selinux_policy)
+ {
+ glnx_throw (error, "Cannot specify --selinux-prefix without --selinux-policy");
+ goto out;
+ }
else if (opt_union)
options.overwrite_mode = OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES;
else if (opt_union_add)
options.process_whiteouts = TRUE;
if (subpath)
options.subpath = subpath;
+
+ g_autoptr(OstreeSePolicy) policy = NULL;
+ if (opt_selinux_policy)
+ {
+ glnx_autofd int rootfs_dfd = -1;
+ if (!glnx_opendirat (AT_FDCWD, opt_selinux_policy, TRUE, &rootfs_dfd, error))
+ {
+ g_prefix_error (error, "selinux-policy: ");
+ goto out;
+ }
+ policy = ostree_sepolicy_new_at (rootfs_dfd, cancellable, error);
+ if (!policy)
+ goto out;
+ options.sepolicy = policy;
+ options.sepolicy_prefix = opt_selinux_prefix;
+ }
+
options.no_copy_fallback = opt_require_hardlinks;
options.force_copy = opt_force_copy;
options.bareuseronly_dirs = opt_bareuseronly_dirs;
cancellable, error))
goto out;
}
-
+
ret = TRUE;
out:
return ret;
if (!instream)
goto out;
}
-
+
datastream = g_data_input_stream_new (instream);
while ((revision = g_data_input_stream_read_upto (datastream, "", 1, &len,
chcon --reference co/usr/bin/bash ${testbin}
newcon=$(getfattr --only-values -m security.selinux ${testbin})
assert_not_streq "${oldcon}" "${newcon}"
-ostree --repo=/ostree/repo commit -b testbranch --link-checkout-speedup \
+ostree commit -b testbranch --link-checkout-speedup \
--selinux-policy co --tree=dir=co
-ostree --repo=/ostree/repo ls -X testbranch /usr/bin/foo-a-generic-binary > ls.txt
+ostree ls -X testbranch /usr/bin/foo-a-generic-binary > ls.txt
assert_file_has_content ls.txt ${oldcon}
-ostree --repo=/ostree/repo fsck
+ostree fsck
-ostree --repo=/ostree/repo refs --delete testbranch
+ostree refs --delete testbranch
rm co -rf
+echo "ok commit with sepolicy"
+
+# Now let's check that selinux policy labels can be applied on checkout
+
+rm rootfs -rf
+if ostree checkout -H \
+ --selinux-policy / ${host_refspec} co; then
+ assert_not_reached "checked out with -H and --selinux-policy"
+fi
+# recommit just two binaries into a new branch with selinux labels stripped
+mkdir -p rootfs/usr/bin
+oldcon=$(getfattr --only-values -m security.selinux /usr/bin/bash)
+cp /usr/bin/{true,bash} rootfs/usr/bin
+newcon=$(getfattr --only-values -m security.selinux rootfs/usr/bin/bash)
+assert_not_streq "${oldcon}" "${newcon}"
+echo "ok checkout with sepolicy setup"
+
+ostree commit -b testbranch rootfs
+ostree checkout testbranch --selinux-policy / co
+newcon=$(getfattr --only-values -m security.selinux co/usr/bin/bash)
+assert_streq "${oldcon}" "${newcon}"
+rm co -rf
+echo "ok checkout with sepolicy"
+ostree checkout testbranch --selinux-policy / --subpath /usr/bin co
+newcon=$(getfattr --only-values -m security.selinux co/bash)
+assert_streq "${oldcon}" "${newcon}"
+rm co -rf
+echo "ok checkout with sepolicy and subpath"
+
+# now commit tree with mismatched leading dirs
+mkdir -p rootfs/subdir
+mv rootfs/{usr,subdir}
+ostree commit -b testbranch rootfs
+ostree checkout testbranch --selinux-policy / co
+newcon=$(getfattr --only-values -m security.selinux co/subdir/usr/bin/bash)
+assert_not_streq "${oldcon}" "${newcon}"
+rm co -rf
+ostree checkout testbranch --selinux-policy / \
+ --subpath subdir --selinux-prefix / co
+newcon=$(getfattr --only-values -m security.selinux co/usr/bin/bash)
+assert_streq "${oldcon}" "${newcon}"
+
+ostree refs --delete testbranch
+rm co -rf
+echo "ok checkout with sepolicy and selinux-prefix"